package com.haiwei.poi.word.bean;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.haiwei.poi.common.HaiweiArrayUtil;
import com.haiwei.poi.common.HaiweiStringUtil;
import com.haiwei.poi.common.exception.HaiweiGeneralException;
import com.haiwei.poi.common.json.HaiweiJsonUtil;
import com.haiwei.poi.common.nassert.HaiweiAssert;
import com.haiwei.poi.common.nassert.HaiweiAssertException;
import com.haiwei.poi.word.exception.HaiweiPoiWordGeneralException;
import com.haiwei.poi.word.manager.HaiweiPatternUtil;
import com.haiwei.poi.word.sign.HaiweiSignConstant;

/**
 * 数据模型工具类.
 *
 * @date: 2022-06-24
 * @version: 1.0
 * @author: karry@haiwei.com
 */
public class HaiweiBeanUtil1 {
    /**
     * 根路径
     */
    private static final String ROOT_PATH = "root";
    
    private static ThreadLocal<HaiweiObject> cache = new ThreadLocal<>();
    private static ThreadLocal<HaiweiBeanCallback> callBackCache = new ThreadLocal<>();
    
    /**
     * 添加数据
     */
    public static void setBean(Object obj) {
        HaiweiAssert.assertNotNull(obj);
        if (obj instanceof String) {
            setJson2Bean(obj.toString());
        } else {
            setJson2Bean(HaiweiJsonUtil.toJson(obj));
        }
    }
    
    public static void setString(String path,Object obj){
        HaiweiAssert.assertNotNull(obj);
        path = HaiweiStringUtil.removeWhitespace(path);
        
        // 如果path为空则放在root下
        if(HaiweiStringUtil.isEmpty(path)){
            path = ROOT_PATH;
        }else{
            path = ROOT_PATH + HaiweiSignConstant.SGIN_PATH_SEPARATOR + path;
        }
        
        if (!HaiweiPatternUtil.checkPathChar(path)) {
            throw new HaiweiAssertException(String.format("path[%s] invalid", path));
        }
        
        String[] paths = path.split(HaiweiSignConstant.SGIN_PATH_SEPARATOR);
        if(cache.get() == null){
            cache.set(HaiweiObject.parseObject("{}"));
        }
        HaiweiObject jsonObject = cache.get();
    
        
        if (obj instanceof String) {
            setJson2Bean(obj.toString());
        } else {
            setJson2Bean(HaiweiJsonUtil.toJson(obj));
        }
    }
    
    private static void setJson2Bean(String json) {
        HaiweiAssert.assertTrue("model can not bean blank", HaiweiStringUtil.isNotBlank(json));
        try {
            HaiweiObject jsonObject = HaiweiObject.parseObject("{'"+ROOT_PATH+"':"+json+"}");
            cache.set(jsonObject);
        } catch (Exception e) {
            throw new HaiweiPoiWordGeneralException("param type must bean json object");
        }
    }
    
    /**
     * 设置回调
     * @param callback
     */
    public static void setCallBackCache(HaiweiBeanCallback callback){
        if(callback != null){
            callBackCache.set(callback);
        }
    }
    
    /**
     * 检出符合的
     *
     * @param cs
     * @return
     */
    @Deprecated
    public static String checkChar(final CharSequence cs) {
        StringBuilder sb = new StringBuilder();
        int strLen = cs != null ? cs.length() : 0;
        char c = 0;
        for (int i = 0; i < strLen; i++) {
            c = cs.charAt(i);
            if ((c >= 'a' && c <= 'z')
                    || (c >= 'A' && c <= 'Z')
                    || (c >= '0' && c <= '9')
                    || c == '.' || c == '[' || c == ']') {
                sb.append(c);
            } else if (Character.isWhitespace(c) == false) {
                throw new HaiweiAssertException(String.format("path[%s] contain invalid char[%c]"
                        , cs, c));
            }
            c = 0;
        }
        return sb.toString();
    }
    
    /**
     * 获取长度
     * @param path
     * @return
     */
    public static int getCollectionLen(String path){
        final Object value = getValue(path);
        if(value == null) {
            return 0;
        }
        
        if(value instanceof JSONArray){
            return ((JSONArray)value).size();
        }
        
        throw new HaiweiGeneralException("expected list but acture type is :" + value.getClass());
    }
    
    
    /**
     * customer.name
     * customer.paths[index].customer 这种场景稍后做
     * paths[1]: ^[a-z|A-Z]?[a-z|A-Z|0-9]+(\[[0-9]+\])?$
     *
     *  if (this_ instanceof JSONObject) {
     *                             bean = (JSONObject) this_;
     *                         } else if (this_ instanceof String) {
     *                             return this_.toString();
     *                         } else if(this_ instanceof JsonArray){
     *                             return this_;
     *                         }
     *
     * @param path
     */
    public static Object getValue(String path) {
        HaiweiAssert.assertNotBlank(path);
        path = HaiweiStringUtil.removeWhitespace(path);
        // path = checkChar(path);
        if (!HaiweiPatternUtil.checkPathChar(path)) {
            throw new HaiweiAssertException(String.format("path[%s] invalid", path));
        }
        
        String[] paths = path.split(HaiweiSignConstant.SGIN_PATH_SEPARATOR);
        if(HaiweiArrayUtil.isEmpty(paths)){
            throw new HaiweiAssertException(String.format("path[%s] invalid", path));
        }
        
        JSONObject bean = cache.get();
        if(bean == null){
            // 如果没有找到就通过回调函数
            HaiweiBeanCallback callback = null;
            if ( (callback = callBackCache.get()) != null) {
                setBean(callback.getBean(path));
            }
            bean = cache.get();
        }
        
        // 再次查询
        if((bean = cache.get()) == null){
            return null;
        }
        
        // 遍历路径
        Object this_ = bean.get(ROOT_PATH);
        int len = paths.length;
        for (int i  = 0 ; i < len ; i++) {
            // String和ArrayList 只能做叶子节点， 有子节点必须是JSONObject类型
            if(!(this_ instanceof JSONObject)){
                throw new HaiweiAssertException(String.format("path[%s],childPath[%s] invalid", path,paths[i]));
            }
            this_ = ((JSONObject)this_).get(paths[i]);
            //标志 还有 但数据已经没了
            if(this_ == null){
                return null;
            }else if(len - i == 1) {
                // 最后一个元素了
                return this_;
            }
        }
        return null;
    }
    
}
